#include "indicator.h"
#include "led.h"
#include "systime.h"
#include "pir_sensor_detect.h"

typedef enum
{
    IND_DET,
    IND_PIR_BLINK,
    IND_BLINK_ON,
    IND_BLINK_OFF,
    IND_BLINK_END,
} IND_STATE;

static struct
{
    timestamp_t time;
    IND_SW sw;
    IND_STATE state;
    uint16_t on_time; // 单位ms
    uint16_t off_time;
    uint8_t blink_flag;
    uint8_t bright_flag; // 指示小灯处于亮的状态还是灭的状态
} ind_ctrl;

typedef enum
{
    PIR_IND_INIT,
    PIR_IND_OCCUPY,
    PIR_IND_DET,
} PIR_IND_E;

static struct
{
    timestamp_t time;
    PIR_IND_E state;
    uint8_t pir_flag; // PIR感应有人则为真，连续1.8s感应无人则为假
} pir_ind;
static void blink_task(void);
static void pir_ind_detect_task(void);
static void set_led_on_off(uint8_t sw);
void indicator_init(void)
{
    led_init();

    ind_ctrl.sw = IND_OFF;
    ind_ctrl.state = IND_DET;
    ind_ctrl.on_time = 80; // 单位ms
    ind_ctrl.off_time = 920;
    ind_ctrl.blink_flag = FALSE;
    ind_ctrl.bright_flag = FALSE;

    pir_ind.state = PIR_IND_INIT;
    pir_ind.pir_flag = FALSE;
}
void indicator_task(void)
{
    pir_ind_detect_task();
    blink_task();
}

static void pir_ind_detect_task(void)
{
    if (IND_PIR != ind_ctrl.sw)
    {
        pir_ind.state = PIR_IND_INIT;
        pir_ind.pir_flag = FALSE;
        return;
    }

    switch (pir_ind.state)
    {
    case PIR_IND_INIT:
        if (pir_sensor_is_occupied())
        { // 感应到有人
            pir_ind.state = PIR_IND_OCCUPY;
        }
        break;
    case PIR_IND_OCCUPY:
        pir_ind.pir_flag = TRUE;
        relative_time_add_ms(&pir_ind.time, 1800); // 连续1.8s感应无人，停止闪烁
        pir_ind.state = PIR_IND_DET;
        break;
    case PIR_IND_DET:
        if (pir_sensor_is_occupied())
        {
            pir_ind.state = PIR_IND_OCCUPY;
        }
        else if (is_relative_time_timeout(&ind_ctrl.time))
        {
            pir_ind.pir_flag = FALSE;
            pir_ind.state = PIR_IND_INIT;
        }
        break;

    default:
        break;
    }
}

static void blink_task(void)
{
    if (!ind_ctrl.blink_flag)
    {
        ind_ctrl.state = IND_DET;
        return;
    }

    switch (ind_ctrl.state)
    {
    case IND_DET:
        if (IND_PIR == ind_ctrl.sw)
        {
            ind_ctrl.on_time = 80;
            ind_ctrl.off_time = 920;
            ind_ctrl.state = IND_PIR_BLINK;
        }
        else if (IND_CUSTOM == ind_ctrl.sw)
        {
            ind_ctrl.on_time = 500;
            ind_ctrl.off_time = 500;
            ind_ctrl.state = IND_BLINK_ON;
        }
        else if (IND_WHITE_SHELL == ind_ctrl.sw)
        {
            ind_ctrl.on_time = 200;
            ind_ctrl.off_time = 200;
            ind_ctrl.state = IND_BLINK_ON;
        }
        else if (IND_BLACK_SHELL == ind_ctrl.sw)
        {
            ind_ctrl.on_time = 900;
            ind_ctrl.off_time = 100;
            ind_ctrl.state = IND_BLINK_ON;
        }
        break;
    case IND_PIR_BLINK:
        if (IND_CUSTOM == ind_ctrl.sw)
        { // 客户自定义环境光，闪烁指示
            ind_ctrl.state = IND_DET;
        }
        else if (IND_WHITE_SHELL == ind_ctrl.sw || IND_BLACK_SHELL == ind_ctrl.sw)
        { // 外壳设置，闪烁指示
            ind_ctrl.state = IND_DET;
        }
        else if (pir_ind.pir_flag)
        { // PIR感应到有人则开始闪烁，连续1.8s内无感应则熄灭
            ind_ctrl.state = IND_BLINK_ON;
        }
        break;
    case IND_BLINK_ON:
        set_led_on_off(ON);
        relative_time_add_ms(&ind_ctrl.time, ind_ctrl.on_time);
        ind_ctrl.state = IND_BLINK_OFF;
        break;
    case IND_BLINK_OFF:
        if (is_relative_time_timeout(&ind_ctrl.time))
        {
            set_led_on_off(OFF);
            relative_time_add_ms(&ind_ctrl.time, ind_ctrl.off_time);
            ind_ctrl.state = IND_BLINK_END;
        }
        break;
    case IND_BLINK_END:
        if (is_relative_time_timeout(&ind_ctrl.time))
        {
            ind_ctrl.state = IND_DET;
        }
        break;

    default:
        break;
    }
}
static void set_led_on_off(uint8_t sw)
{
    if (sw)
    {
        set_led(ON);
        ind_ctrl.bright_flag = TRUE;
    }
    else
    {
        set_led(OFF);
        ind_ctrl.bright_flag = FALSE;
    }
}

void set_indicator_sw(IND_SW sw)
{
    ind_ctrl.sw = sw;

    if (IND_OFF == ind_ctrl.sw)
    {
        ind_ctrl.blink_flag = FALSE;
        set_led_on_off(OFF);
    }
    else if (IND_ON == ind_ctrl.sw)
    {
        ind_ctrl.blink_flag = FALSE;
        set_led_on_off(ON);
    }
    else
    {
        ind_ctrl.blink_flag = TRUE;
        set_led_on_off(OFF);
    }
}

// 获取指示灯当前的指示状态
IND_SW get_indicator_sw(void)
{
    return ind_ctrl.sw;
}

// 获取指示灯当前的亮暗状态
uint8_t is_indicator_bright(void)
{
    return ind_ctrl.bright_flag;
}
